home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / osr5 / sco / scripts / unixtime < prev    next >
Encoding:
AWK Script  |  1997-08-26  |  8.5 KB  |  240 lines

  1. #!/usr/local/bin/gawk -f
  2. # @(#) unixtime.gawk 2.1 97/04/15
  3. # 92/09/12 john h. dubois iii (john@armory.com)
  4. # 93/01/27 added printing of systime() if no args given
  5. # 93/05/11 Use long date format string instead of %c in case %c doesn't work
  6. # 95/10/11 Allow format to be set
  7. # 96/12/16 Added epoch day<->date capability.
  8.  
  9. # Use gawk for systime() and strftime()
  10.  
  11. BEGIN {
  12.     Name = "unixtime"
  13.     Usage = "Usage: " Name " [-hi] [time|format|date ...]"
  14.     Format = "%a %b %d %T %Z %Y"
  15.     FmtUsed = 1
  16.     CurTime = systime()
  17.     if (ARGC == 1)    # If no args, print epoch time
  18.     print CurTime
  19.     else {
  20.     if (ARGV[1] ~ "^[-+]h$")
  21.         printf \
  22. "%s: convert UNIX times, given as the number of seconds since the\n"\
  23. "epoch (1970 Jan 1 GMT), to a local time in human readable format.\n"\
  24. "%s\n"\
  25. "If no arguments are given, the current epoch time (in seconds) is printed.\n"\
  26. "If arguments are given, they should be time formats, epoch times, or\n"\
  27. "dates.\n"\
  28. "Time formats and epoch times:\n"\
  29. "If an argument has a %% character in it or consists of the '.' character,\n"\
  30. "it is taken to be a time format, and causes any further times that are\n"\
  31. "printed to be converted using the given format.  Time formats are as\n"\
  32. "described in the strftime(S) and date(C) man pages, except that a time\n"\
  33. "format consisting solely of a '.' character causes the time to be printed\n"\
  34. "as an epoch time.  If an argument consists entirely of digits, it is taken\n"\
  35. "to be an epoch time, and is printed using the most recently specified\n"\
  36. "format (arguments are processed from left to right).  If no format has\n"\
  37. "been given, the default format of \"%s\" is used.  If the time\n"\
  38. "format is changed without the prior format having been used (that is, if\n"\
  39. "multiple time formats are given in succession without epoch times between\n"\
  40. "them), then the current time is printed using the prior format before it\n"\
  41. "is changed.  The same applies if the last argument is a time format.  A\n"\
  42. "null (empty) argument is short for the current time.  The current time is\n"\
  43. "the time the program started if arguments on the command line are being\n"\
  44. "processed (for consistency), but is the time of printing for arguments\n"\
  45. "read from the standard input, so that formats or null strings may be\n"\
  46. "entered at intervals and get the current time.  Example:\n"\
  47. "%s 813444165 '%%D %%T' %%c 813444200 %%W\n"\
  48. "This prints the first time (81344165) using the default format, then the\n"\
  49. "current time as a date and time (%%D %%T) because that format is not used\n"\
  50. "before the format is changed again, then prints the second time (81344200)\n"\
  51. "in the 'local format' (%%c), then prints the current week of the year\n"\
  52. "(%%W).\n"\
  53. "Dates:\n"\
  54. "If an argument contains no %% characters and does contain / characters, it\n"\
  55. "is taken to be a date in the form year/month/day.  If a year less than 70\n"\
  56. "is given, it is taken to be relative to the year 2000; if a year between 70\n"\
  57. "and 99 is given, it is taken to be relative to the year 1900.  For each\n"\
  58. "date given, the epoch day (the number of days since 1970 Jan 1) is printed.\n"\
  59. "If an argument with the form <number>d is given, it is taken to be an\n"\
  60. "epoch day, and the equivalent date in the form year/month/day is printed.\n"\
  61. "Options:\n"\
  62. "-h: Print this help.\n"\
  63. "-i: Read times and formats from the standard input instead of using values\n"\
  64. "    given on the command line.  The times and formats should be given one\n"\
  65. "    per line.\n",
  66.         Name,Usage,Format,Name
  67.     else if (ARGV[1] ~ "^[-+]i$") {
  68.         while ((getline < "/dev/stdin") == 1)
  69.         if (Convert($0,-1)) {
  70.             printf "Bad value: '%s'\n",$0
  71.             exit 1
  72.         }
  73.         if (!FmtUsed)
  74.         xstrftime(Format,-1)
  75.     }
  76.     else {
  77.         for (i = 1; i < ARGC; i++)
  78.         if (Convert(ARGV[i],CurTime)) {
  79.             printf "Invalid argument: '%s'\n%s\n",ARGV[i],Usage
  80.             exit 1
  81.         }
  82.         if (!FmtUsed)
  83.         xstrftime(Format,CurTime)
  84.     }
  85.     }
  86. }
  87.  
  88. # If Time is -1, systime() is used, if not, Time is used.
  89. function xstrftime(Format,Time) {
  90.     if (Time == -1)
  91.     Time = systime()
  92.     if (Format == ".")
  93.     printf "%d\n",Time
  94.     else
  95.     print strftime(Format,Time)
  96. }
  97.  
  98. # Val is a time, format, or date.
  99. function Convert(Val,CurTime,  ret) {
  100.     if (Val ~ "%." || Val == ".") {
  101.     if (!FmtUsed)
  102.         xstrftime(Format,CurTime)
  103.     Format = Val
  104.     FmtUsed = 0
  105.     }
  106.     else if (Val == "" || Val ~ "^[0-9]+$") {
  107.     xstrftime(Format,Val == "" ? CurTime : Val)
  108.     FmtUsed = 1
  109.     }
  110.     else if (Val ~ "^[0-9]+/[0-9]+/[0-9]+$") {
  111.     if ((ret = date2day(Val)) == -1)
  112.         return 1
  113.     else
  114.         print ret
  115.     }
  116.     else if (Val ~ "^[0-9]+d$")
  117.     print day2date(substr(Val,1,length(Val)-1),1)
  118.     else
  119.     return 1
  120.     return 0
  121. }
  122.  
  123. ### Begin epochdays routines.
  124. # These functions operate on epoch days and epoch months, which have the same 0
  125. # time as UNIX epoch seconds.  These functions are mainly used to avoid having
  126. # to deal with timezone issues.
  127. # @(#) epochdays 1.1 95/08/26
  128.  
  129. # YMD2day(year,month,day-of-month) returns the number of days that passed from 
  130. # 1970 Jan 1 to the given date.
  131. # All parameters should be given in numeric form.
  132. # If year < 70, it is assumed to be part of the 2000 century
  133. # If year in (70..99), it is assumed to be part of the 1900 century.
  134. # Globals: sets and uses MDays[]
  135. function YMD2day(Year,Month,Day,   LeapDays) {
  136.     Year+=0
  137.     Month+=0
  138.     if (Year < 70)
  139.     Year += 100
  140.     else if (Year >= 100)
  141.     Year -= 1900
  142.     # Year is now the number of years since 1900.
  143.     LeapDays = int((Year - 68) / 4)
  144.     if (Month <= 2 && Year % 4 == 0)
  145.     LeapDays -= 1
  146.     if (!(0 in MDays))
  147.     split("0 31 59 90 120 151 181 212 243 273 304 334 365",MDays," ")
  148.     return (Year - 70) * 365 + MDays[Month] + Day - 1 + LeapDays
  149. }
  150.  
  151. # date2day("yy/mm/dd") returns the number of days that passed from 
  152. # 1970 Jan 1 to the given date.  -1 is returned on error.
  153. # The fields are returned in Fields: year in Fields[1], month in Fields[2],
  154. # and day (if given) in Fields[3].
  155. function date2day(Date,Fields,  Num,Year,Month) {
  156.     Num = split(Date,Fields,"/")
  157.     if (Num != 2 && Num != 3)
  158.     return -1
  159.     if (!(Year = Fields[1] + 0) || !(Month = Fields[2] + 0))
  160.     return -1
  161.     if (Num == 3)
  162.     Day = Fields[3]
  163.     return YMD2day(Year,Month,Day)
  164. }
  165.  
  166. # diffdays(year1,month1,day-of-month1,year2,month2,day-of-month2)
  167. # returns the number of complete days that passed from date 1 to date 2
  168. function diffdays(year1,month1,day1,year2,month2,day2) {
  169.     return YMD2day(year2,month2,day2) - YMD2day(year1,month1,day1)
  170. }
  171.  
  172. # Given an epoch month, return the first day of that month
  173. function month2day(Month) {
  174.     return YMD2day(int(Month/12) + 1970,Month % 12 + 1,1)
  175. }
  176.  
  177. # Given an epoch day, returns epoch month
  178. function day2month(Day,  Date) {
  179.     day2YMD(Day,Date)
  180.     return (Date["y"]-1970)*12 + Date["m"]-1
  181. }
  182.  
  183. # Given an epoch month, returns the number of days in that month.
  184. function monthdays(month,  year) {
  185.     if (!(0 in MDur))
  186.     split("31 28 31 30 31 30 31 31 30 31 30 31",MDur)
  187.     year = int(month/12)
  188.     month = month%12+1
  189.     return (!((year+2)%4) && month == 2) ? 29 : MDur[month]
  190. }
  191.  
  192. # Given an epoch day (day since 1970 Jan 1; day 0 = 1970 Jan 1, etc.), 
  193. # returns the date elements in Date:
  194. # Date["y"] = year (4 digits), Date["m"] = month (jan = 1, etc.),
  195. # Date["d"] = day of month.
  196. # Globals: Sets/uses MDays[].
  197. function day2YMD(Day,Date,  QYears,Year,NonLeapYears,Month) {
  198.     if (!(0 in LDays)) {
  199.     split("0 31 59 90 120 151 181 212 243 273 304 334 365",MDays," ")
  200.     split("0 31 60 91 121 152 182 213 244 274 305 335 366",LDays," ")
  201.     }
  202.     Day += 365
  203.     # Day is now # of days since Jan 1 1969.  1968 was a leap year.
  204.     QYears = int(Day / (365*4+1))
  205.     Year = 1969 + QYears * 4
  206.     Day -= QYears * (365*4+1)
  207.     # Day now contains no complete leap years.
  208.     Year += NonLeapYears = int(Day/365)
  209.     Leap = !(Year % 4)
  210.     Day -= NonLeapYears * 365
  211.     # Day now contains the day of year.
  212.     # Find the month.  Divide day by 32 to get either the correct month or
  213.     # the month prior to it.
  214.     Month = int(Day++ / 32) + 1
  215.     if (Day > (Leap ? LDays[Month+1] : MDays[Month+1]))
  216.     Month++
  217.     Day -= Leap ? LDays[Month] : MDays[Month]
  218.     Date["d"] = Day
  219.     Date["m"] = Month
  220.     Date["y"] = Year
  221. }
  222.  
  223. # Given a month number, return a date in the form yy/mm
  224. function month2date(MonthNum) {
  225.     return sprintf("%02d/%02d",(MonthNum / 12 + 70) % 100, MonthNum % 12 + 1)
  226. }
  227.  
  228. # Given a day number, return a date in the form yy/mm/dd or yyyy/mm/dd
  229. # If century is true, the century is included as part of the year;
  230. # otherwise it is stripped.
  231. function day2date(day,century,  year) {
  232.     day2YMD(day,Date)
  233.     year = Date["y"]
  234.     if (!century)
  235.     year %= 100
  236.     return sprintf("%02d/%02d/%02d",year,Date["m"],Date["d"])
  237. }
  238.  
  239. ### End epochdays routines
  240.